package cc.autoapi.pucong.auto.flow.core.flow.execNode.task.extend;


import cc.autoapi.pucong.auto.flow.core.flow.execNode.exception.AutoDesignException;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.utils.javaLoader.DynamicLoader;
import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * @description:
 * @author: cong.pu
 * @create: 2024-09-30 10:24
 **/
@Slf4j
public class ExtendTaskInstance {

    public static void main(String[] args) {
        String source = "package cc.autoapi.pucong.auto.flow.auto.core.flow.execNode.task.extend.demo;\n" +
                "\n" +
                "\n" +
                "import cc.autoapi.pucong.auto.flow.auto.core.flow.execNode.entity.node.NodeParamIn;\n" +
                "import cc.autoapi.pucong.auto.flow.auto.core.flow.execNode.entity.node.NodeParamOut;\n" +
                "import cc.autoapi.pucong.auto.flow.auto.core.flow.execNode.entity.task.NodeExecResult;\n" +
                "import cc.autoapi.pucong.auto.flow.auto.core.flow.execNode.selfenum.DataTypeEnum;\n" +
                "import cc.autoapi.pucong.auto.flow.auto.core.flow.execNode.task.extend.AbstractExtendTask;\n" +
                "\n" +
                "import java.util.ArrayList;\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @description:\n" +
                " * @author: cong.pu\n" +
                " * @create: 2024-09-30 10:28\n" +
                " **/\n" +
                "public class DemoExtendTask extends AbstractExtendTask {\n" +
                "\n" +
                "    private List<NodeParamIn> paramsIns;\n" +
                "    private List<NodeParamOut> paramsOuts;\n" +
                "\n" +
                "    public DemoExtendTask() {\n" +
                "        paramsIns = new ArrayList<>();\n" +
                "        NodeParamIn url = new NodeParamIn()\n" +
                "                .setParamCode(\"url\")\n" +
                "                .setDateType(DataTypeEnum.STRING)\n" +
                "                .setDesc(\"请求地址\")\n" +
                "                .setDefaultValue(\"http://www.baidu.com\")\n" +
                "                .setNeedValue(true);\n" +
                "        paramsIns.add(url);\n" +
                "        NodeParamIn methodType = new NodeParamIn()\n" +
                "                .setParamCode(\"methodType\")\n" +
                "                .setDateType(DataTypeEnum.STRING)\n" +
                "                .setDesc(\"请求方法类型，例：POST、GET、DELETE、PUT\")\n" +
                "                .setDefaultValue(\"POST\")\n" +
                "                .setNeedValue(true);\n" +
                "        paramsIns.add(methodType);\n" +
                "        NodeParamIn contentType = new NodeParamIn()\n" +
                "                .setParamCode(\"contentType\")\n" +
                "                .setDateType(DataTypeEnum.STRING)\n" +
                "                .setDesc(\"请求方法类型，例：application/json; charset=utf-8\")\n" +
                "                .setDefaultValue(\"application/json; charset=utf-8\")\n" +
                "                .setNeedValue(true);\n" +
                "        paramsIns.add(contentType);\n" +
                "        NodeParamIn bodyParams = new NodeParamIn()\n" +
                "                .setParamCode(\"bodyParams\")\n" +
                "                .setDateType(DataTypeEnum.OBJECT)\n" +
                "                .setDefaultValue(\"{}\")\n" +
                "                .setNeedValue(false);\n" +
                "        paramsIns.add(bodyParams);\n" +
                "        NodeParamIn headerParams = new NodeParamIn()\n" +
                "                .setParamCode(\"headerParams\")\n" +
                "                .setDateType(DataTypeEnum.OBJECT)\n" +
                "                .setDefaultValue(\"{}\")\n" +
                "                .setNeedValue(false);\n" +
                "        paramsIns.add(headerParams);\n" +
                "        NodeParamIn queryParams = new NodeParamIn()\n" +
                "                .setParamCode(\"queryParams\")\n" +
                "                .setDateType(DataTypeEnum.OBJECT)\n" +
                "                .setDefaultValue(\"{}\")\n" +
                "                .setNeedValue(false);\n" +
                "        paramsIns.add(queryParams);\n" +
                "\n" +
                "        paramsOuts = new ArrayList<>();\n" +
                "        NodeParamOut data = new NodeParamOut()\n" +
                "                .setParamCode(\"data\")\n" +
                "                .setDesc(\"返回值\")\n" +
                "                .setDateType(DataTypeEnum.OBJECT);\n" +
                "        paramsOuts.add(data);\n" +
                "        NodeParamOut status = new NodeParamOut()\n" +
                "                .setParamCode(\"status\")\n" +
                "                .setDesc(\"接口调用状态\")\n" +
                "                .setDateType(DataTypeEnum.NUMBER);\n" +
                "        paramsOuts.add(status);\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public NodeExecResult run() {\n" +
                "        System.out.println(\"demo\");\n" +
                "        return NodeExecResult.ok();\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public List<NodeParamIn> getPropertyParamsIns() {\n" +
                "        return paramsIns;\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String getTaskName() {\n" +
                "        return \"demo\";\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public List<NodeParamOut> getPropertyParamsOuts() {\n" +
                "        return paramsOuts;\n" +
                "    }\n" +
                "}\n";
        AbstractScriptTask task = getTask(source);
        System.out.println(task.handle(new JSONObject()));
    }

    public static <T extends AbstractScriptTask> T getTask(String script) {
        T t = null;
        try {
            t = (T) invoke(script).newInstance();
        } catch (Exception e) {
            log.error("getTask error", e);
            throw new AutoDesignException("获取任务类型失败");
        }
        return t;
    }

    public static Class<? extends AbstractScriptTask> invoke(String script) throws Exception {
        String packageName = ReUtil.getGroup1("package\\s+([\\w\\.]+)\\s*;", script);
        String className = ReUtil.getGroup1("class\\s+(\\w+)\\s+extends\\s+AbstractScriptTask", script);

        String classNamePath = packageName + "." + className;

        final String SUFFIX = ".java";// 类名后面要跟的后缀

        // 对source进行编译生成class文件存放在Map中，这里用bytecode接收
        Map<String, byte[]> bytecode = DynamicLoader.compile(classNamePath + SUFFIX, script);

        // 加载class文件到虚拟机中，然后通过反射执行
        @SuppressWarnings("resource")
        DynamicLoader.MemoryClassLoader classLoader = new DynamicLoader.MemoryClassLoader(bytecode);
        Class<? extends AbstractScriptTask> clazz = (Class<? extends AbstractScriptTask>) classLoader.loadClass(classNamePath);
        return clazz;
    }
}
